using System;
using AndyPike.Snowflake.Core.Exceptions;
using AndyPike.Snowflake.Core.Messages;
using AndyPike.Snowflake.Core.Queries.Accounts;
using AndyPike.Snowflake.Entities;
using NUnit.Framework;
using NUnit.Framework.SyntaxHelpers;
using Rhino.Mocks;

namespace AndyPike.Snowflake.Core.Tests.Unit.Services.AccountServiceFixtures
{
    [TestFixture]
    public class When_authenticating_credentials : AccountServiceFixtureBase
    {
        [Test]
        [ExpectedException(typeof(ArgumentNullException))]
        public void Should_throw_an_exception_of_the_message_is_null()
        {
            service.AuthenticateCredentials(null);
        }

        [Test]
        public void Should_validate_the_credentials()
        {
            var credentials = mockery.Stub<CredentialsMessage>();
            credentials.UserName = "andy";
            credentials.Password = "blah";

            With.Mocks(mockery)
                .Expecting(delegate
                {
                    Expect.Call(credentials.Validate);
                    SetupResult.For(accountRepository.FindOne(null)).IgnoreArguments().Return(new Account());
                })
                .Verify(() => service.AuthenticateCredentials(credentials));
        }

        [Test]
        public void Should_leverage_the_repository_to_retrieve_the_account_with_matching_user_name_and_password()
        {
            Guid authenticationToken = Guid.Empty;
            var account = new Account { Id = Guid.NewGuid() };
            var credentials = new CredentialsMessage{ UserName = "andy", Password = "blah"};

            With.Mocks(mockery)
                .Expecting(() => Expect.Call(accountRepository.FindOne(Arg<AccountByUserNameAndPassword>.Is.TypeOf)).Return(account))
                .Verify(() => authenticationToken = service.AuthenticateCredentials(credentials));

            Assert.That(authenticationToken, Is.EqualTo(account.Id));
        }

        [Test]
        [ExpectedException(typeof(AuthenticationFailedException))]
        public void Should_throw_an_exception_if_the_credentials_are_invalid()
        {
            var credentials = new CredentialsMessage { UserName = "andy", Password = "blah" };

            With.Mocks(mockery)
                .Expecting(() => Expect.Call(accountRepository.FindOne(Arg<AccountByUserNameAndPassword>.Is.TypeOf)).Return(null))
                .Verify(() => service.AuthenticateCredentials(credentials));
        }
    }
}